/**
 * @file mrobot.h
 * @author HelloKun （https://space.bilibili.com/475950146）
 * @brief 智慧终端机器人MRobot -详细功能说明见mrobot.h
 * @version 0.1 ，关闭oled显示，提升NAN配网成功率；先初始化mpu等，再启动NAN；控制大量使用switch 配合return实现较快响应
 * @date
 *       2021.12-2022.04: 南北向基础
 *       2022.03.16: 实现基础运动控制
 *       2022.04-05：APP UI 与硬件联动
 *       2022.05.16-06.14 优化 
 *              提供风扇、台灯亮度调节；
 *              连接任意一台互联设备，即可通过机器人控制所有设备
 *              将常量宏定义，减少魔法变量，便于理解和增添设备。
 *      Tips：关闭oled显示，NAN效率更高，开机实现不到一秒连接
 * @copyright Copyright (c) 2022
 *
 */
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <unistd.h>
#include "string.h"

#include "ohos_init.h"
#include "cmsis_os2.h"
#include "securec.h"
#include "ohos_types.h"

#include "touch_sensor.h"
#include "bluetooth.h"
#include "speaker.h"
#include "motor.h"
#include "oled_ssd1306.h"
#include "netcfg.h"
#include "network_config_service.h"
#include "defines.h"
#include "mrobot.h"
#include "mpu6050.h"

#define TOUCH_VALUE 130
#define MESSAGE_LEN 6
#define circle_time 1000000 //机器人一次运动时间

static bool m_netstatus = false;
char app_msg[12] = {'0'};

//unsigned char ble_send_data[12] = {'0'}; //蓝牙发送缓冲
unsigned char get_ble_data[8] = {'0'};   //蓝牙接收缓存

unsigned char mrobot2sut03[] = {0xAA, 0x55, 0x00, 0x55, 0xAA};
unsigned char sut032mrobot[] = {0xAA, 0x55, 0x00, 0x55, 0xAA};
// unsigned char mrobot2fan[] = {'1', '0'};
// unsigned char mrobot2door[] = {'2', '0'};
// unsigned char mrobot2lamb[] = {'3', '0'};
// unsigned char mrobot2water[] = {'4', '0'}; // 宏定义替代了局部变量 

short aacx, aacy, aacz;    //加速度传感器原始数据
short gyrox, gyroy, gyroz; //陀螺仪原始数据
int mpu_temp;              //陀螺仪本身自带温度传感

static void MRobotProcessAppMessage(const char *data, int data_len)
{
    if (data_len != MESSAGE_LEN)
    {
        strcpy(app_msg, data);
        printf("------app_msg:%s \r\n", app_msg);
        printf("------raw data:%s\r\n", data);
        return;
    }
}

static int MRobotNetEventHandler(NET_EVENT_TYPE event, void *data)
{
    switch (event)
    {
    case NET_EVENT_CONNECTTED: // 网络连接成功
        m_netstatus = true;
        printf("m_netstatus:%d\n\n", m_netstatus); // 显示网络已连接
        break;
    case NET_EVENT_RECV_DATA:                                      // 接收到网络信息(FA发送的消息)
        MRobotProcessAppMessage((const char *)data, strlen(data)); // 处理对应的信息
        break;
    default:
        break;
    }
    return 0;
}

//严格按照【自定义MRobot与互联设备间数据帧.txt】判断数据
//app ctr mrobot moving; app运动控制
static void AppCtrMRobot()
{
    switch (*app_msg)
    {
    case FORWARD:
    {
        printf("退下\r\n");
        // OledFillScreen(0x00);
        // OledShowString(25, 2, "Forward", 2);
        Backward(circle_time);
        Stop_motor();
        return; //每次仅有一种情况，满足直接return回main
    }
    case BACKWARD:
    {
        printf("过来\r\n");
        // OledFillScreen(0x00);
        // OledShowString(25, 2, "Backward", 2);
        Forward(circle_time);
        Stop_motor();
        return;
    }
    case TURN_LEFT:
    {
        printf("左转\r\n");
        // OledFillScreen(0x00);
        // OledShowString(25, 2, "Turn Left", 2);
        Turn_left(circle_time);
        Stop_motor();
        return;
    }
    case TURN_RIGHT:
    {
        printf("右转\r\n");
        // OledFillScreen(0x00);
        // OledShowString(25, 2, "Turn Right", 2);
        Turn_right(circle_time);
        Stop_motor();
        return;
    }
    case CIRCLE:
    {
        printf("转圈\r\n");
        // OledFillScreen(0x00);
        // OledShowString(25, 2, "Circle running", 2);
        Circle(circle_time);
        Stop_motor();
        return;
    }
    default:
    {
        return;
    }
    }
}

// speaker ctr mrobot moving
static void SpeakerCtrMRobot()
{
    switch (sut032mrobot[2])
    {
    case TURN_LEFT_S:
    {
        printf("左转\r\n");
        // OledFillScreen(0x00);
        // OledShowString(25, 2, "Turn Left", 2);
        Turn_left(circle_time);
        Stop_motor();
        return;
    }
    case TURN_RIGHT_S:
    {
        printf("右转\r\n");
        // OledFillScreen(0x00);
        // OledShowString(25, 2, "Turn Right", 2);
        Turn_right(circle_time);
        Stop_motor();
        return;
    }
    case FORWARD_S:
    {
        printf("过来\r\n");
        // OledFillScreen(0x00);
        // OledShowString(25, 2, "Forward", 2);
        Forward(circle_time);
        Stop_motor();
        return;
    }
    case BACKWARD_S:
    {
        printf("退下\r\n");
        // OledFillScreen(0x00);
        // OledShowString(25, 2, "Backward", 2);
        Backward(circle_time);
        Stop_motor();
        return;
    }
    case CIRCLE_S:
    {
        printf("转圈\r\n");
        // OledFillScreen(0x00);
        // OledShowString(25, 2, "Circle running", 2);
        Circle(circle_time);
        Stop_motor();
        return;
    }
    default:
    {
        return;
    }
    }
}
// union devices ctr 互联设备【风扇、门锁、台灯、养花机】控制
static void UnionDeviceCtr()
{
    // speaker ctr to union devices
    switch (sut032mrobot[2])
    {
    case FAN_LEV_1_S:                        //fan
    {
        printf("turn on fan Lev-1 \n");
        Bluetooth_write(FAN_LEV_1, UNION_CMD_LEN);
        break;
    }
    case FAN_LEV_2_S:
    {
        printf("turn on fan Lev-2 \n");
        Bluetooth_write(FAN_LEV_2, UNION_CMD_LEN);
        break;
    }
    case FAN_LEV_3_S:
    {
        printf("turn on fan Lev-3 \n");
        Bluetooth_write(FAN_LEV_3, UNION_CMD_LEN);
        break;
    }
    case FAN_OFF_S:
    {
        printf("turn off fan\n");
        Bluetooth_write(FAN_OFF, UNION_CMD_LEN);
        break;
    }
    case DOOR_OPEN_S:                         //door
    {
        Bluetooth_write(DOOR_OPEN, UNION_CMD_LEN);
        break;
    } 
    case LAMB_LEV_1_S:                        //lamb
    {
        Bluetooth_write(LAMB_LEV_1, UNION_CMD_LEN);//'31'
        break;
    }
    case LAMB_LEV_2_S:
    {
        Bluetooth_write(LAMB_LEV_2, UNION_CMD_LEN);//'32'
        break;
    }
    case LAMB_LEV_3_S:
    {
        Bluetooth_write(LAMB_LEV_3, UNION_CMD_LEN);//'33'
        break;
    }
    case LAMB_OFF_S:
    {
        Bluetooth_write(LAMB_OFF, UNION_CMD_LEN);
        break;
    }
    case WATER_GO_S:                        //water
    {
        Bluetooth_write(WATER_GO, UNION_CMD_LEN);
        break;
    }
    case 0x51: //播报温度--使用mpu6050时可将数据传输过去，默认不使用，这里发个22.8℃测试温度
    {
        unsigned char temperature_data[] = {0xAA, 0x55, 0x09, 0x16, 0x08, 0x55, 0xAA}; //  0x16, 0x08, 22.8℃
        Bluetooth_write(temperature_data, TEMP_LEN);
        break;
    }
    default:
    {
        break;
    }
    }

   //mqtt ctr to union devices
    if (strcmp(app_msg, "turn on fan lev1") == 0)
    {
        Bluetooth_write(FAN_LEV_1, UNION_CMD_LEN);//'11'
        return;
    }
    if (strcmp(app_msg, "turn on fan lev2") == 0)
    {
        Bluetooth_write(FAN_LEV_2, UNION_CMD_LEN);//'12'
        return;
    }
    if (strcmp(app_msg, "turn on fan lev3") == 0)
    {
        Bluetooth_write(FAN_LEV_3, UNION_CMD_LEN);//'13'
        return;
    }
    if (strcmp(app_msg, "turn off fan") == 0)
    {
        Bluetooth_write(FAN_OFF, UNION_CMD_LEN);//'10'
        return;
    }
    if (strcmp(app_msg, "open door") == 0)
    {
        Bluetooth_write(DOOR_OPEN, UNION_CMD_LEN);//'21'
        return;
    }
    if (strcmp(app_msg, "turn on lamb lev1") == 0)
    {
        Bluetooth_write(LAMB_LEV_1, UNION_CMD_LEN);//'31'
        return;
    }
    if (strcmp(app_msg, "turn on lamb lev2") == 0)
    {
        Bluetooth_write(LAMB_LEV_2, UNION_CMD_LEN);//'32'
        return;
    }
    if (strcmp(app_msg, "turn on lamb lev3") == 0)
    {
        Bluetooth_write(LAMB_LEV_3, UNION_CMD_LEN);//"33"
        return;
    }
    if (strcmp(app_msg, "turn off lamb") == 0)
    {
        Bluetooth_write(LAMB_OFF, UNION_CMD_LEN);//"30"
        return;
    }
    if (strcmp(app_msg, "go ahead water") == 0)
    {
        Bluetooth_write(WATER_GO, UNION_CMD_LEN); //"41"
        return;
    }
    return;
}

// sut03交互 emoji number 1-8 
static void AppMsg2Speaker()
{
    switch (*app_msg)
    {
    case EMOJI_1:
    {
        mrobot2sut03[2] = 0x01;
        break;
    }
    case EMOJI_2:
    {
        mrobot2sut03[2] = 0x02;
        break;
    }
    case EMOJI_3:
    {
        mrobot2sut03[2] = 0x03;
        break;
    }
    case EMOJI_4:
    {
        mrobot2sut03[2] = 0x04;
        break;
    }
    case EMOJI_5:
    {
        mrobot2sut03[2] = 0x05;
        break;
    }
    case EMOJI_6:
    {
        mrobot2sut03[2] = 0x06;
        break;
    }
    case EMOJI_7:
    {
        mrobot2sut03[2] = 0x07;
        break;
    }
    case EMOJI_8:
    {
        mrobot2sut03[2] = 0x08;
        break;
    }
    case ON_OFF: //app页面左上角ON开关 温度测试
    {
        unsigned char temperature_data[] = {0xAA, 0x55, 0x09, 0x16, 0x08, 0x55, 0xAA}; //  0x16, 0x08, 22.8℃
        Bluetooth_write(temperature_data, TEMP_LEN);
        return;
    }
    default:
    {
        return; //不播报
    }
    }
    Bluetooth_write(mrobot2sut03, SUT03_LEN);
    return;
}

static void MRobot_Init()
{
    if (Bluetooth_Init() >= 0)
    {
        printf("Bluetooth initial successful\n");
    }
    if (Speaker_Init() >= 0)
    {
        printf("Speaker initial successful\n");
    }
    TouchSensorInit();
    Motor_Init();

    // MPU_Init(); //与Oled同时只能使用一个
    /*while (MPU_Init())
    {
        printf("MPU Initialize Faild \n");
    }*/


    // OledInit();
    // OledFillScreen(0x00);
    // OledShowString(25, 2, "Hello", 2); //==位置、内容、大小1、2可选
    // sleep(2);
    // OledFillScreen(0x00);
    // OledShowString(30, 2, "Kun", 2); //==位置、内容、大小1、2可选
    // sleep(1);
    // OledFillScreen(0x00);
    // OledShowString(25, 2, "HarmonyOS", 2); //==位置、内容、大小1、2可选
    // sleep(2);
    // OledFillScreen(0x00);
    // OledFillScreen(0x00);
    // for (int y = 0; y < 1; y++)
    // {
    //     OledShowString(0, y, "Hello,HarmonyOS", 2); //==位置、内容、大小1、2可选
    // }
    // sleep(1);
    // OledFillScreen(0x00);
    // OledShowString(25, 2, "I am MRobot", 2);
}

static void *MRobotTask(const char *arg)
{
    (void)arg;
    MRobot_Init();
    NetCfgRegister(MRobotNetEventHandler); // 进入配网状态并注册网络监听事件
    int ret;

    float touch_val = 0;
    while (1)
    {
        //使用 mpu6050 需要打开i2c 并在build中配置参与编译
        // mpu_temp = MPU_Get_Temperature();
        // MPU_Get_Gyroscope(&gyrox,&gyroy,&gyroz);
        // MPU_Get_Accelerometer(&aacx,&aacy,&aacz);
        // Print_Original_MPU_Data();
        // printf("loop temperature = %d \n",mpu_temp);

        touch_val = Get_touch_val();
        // printf("touch_val= %.3f \n", touch_val);

        if (touch_val > TOUCH_VALUE)
        {
            // OledFillScreen(0x00);
            // OledShowSmile(0, 0, 31);
            // Bluetooth_write(temperature_data, TEMP_LEN);
            mrobot2sut03[2] = 0x01; //喵喵喵
            Bluetooth_write(mrobot2sut03, SUT03_LEN);
            // Speaker_write(mrobot2sut03, SUT03_LEN);
        }

        ret = Bluetooth_read(sut032mrobot, SUT03_LEN);
        printf("ret bluetooth read:  %d \n", ret);
        // printf("sut032mrobot:%0x \n", sut032mrobot);
        if (sut032mrobot[2] != ALL_DATA_INIT_0)
        {
            SpeakerCtrMRobot();
        }
        if (app_msg[0] != ALL_DATA_INIT_C0)
        {
            AppCtrMRobot();
            AppMsg2Speaker();
        }
        if ((sut032mrobot[2] != ALL_DATA_INIT_0) || (app_msg[0] != ALL_DATA_INIT_C0))
        {
            UnionDeviceCtr();
        }
        SendRawData(app_msg); // 将收到的消息发到APP 作为通信正常反馈；也可发送任何数据如温度，但仅限字符串形式
        //循环之前-初始化数据容器
        app_msg[0] = ALL_DATA_INIT_C0;
        get_ble_data[0] = ALL_DATA_INIT_C0;
        sut032mrobot[2] = ALL_DATA_INIT_0;
        osDelay(200);
    }
}

static void MRobotEntry(void)
{
    osThreadAttr_t attr;
    attr.name = "MRobotTask";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 4096;
    attr.priority = 25;

    if (osThreadNew(MRobotTask, NULL, &attr) == NULL)
    {
        printf("[MRobotTask] Falied to create HeibotTask!\n");
    }
}
// APP_FEATURE_INIT(MRobotEntry);
SYS_RUN(MRobotEntry);